package dse.messages.singleversion;

import dse.messages.*;
import dse.*;
import java.util.*;

public class RequestLockMessageHandler extends MessageSender implements
		MessageHandler {
	private DataObject dobj;
	private DataRequest request;
	private LockProcessor processor;
	
	public RequestLockMessageHandler(Experiment experiment, DataObject dobj, DataRequest request, LockProcessor lp){
		super(experiment);
		this.dobj = dobj;
		this.request = request;
		this.processor = lp;
	}
	@Override
	public boolean acceptMessage(Message message) {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public void messageInterupted(ExperimentRecorder recorder, Message message,
			double currentTime) {
		// TODO Auto-generated method stub
		//recorder.debug(this, "msgIntrpt: " + message, currentTime);
		processor.lockProcess(false, message.from(), recorder, currentTime);
		/*if(message.to().id() == 566){
				System.out.println("Node " + message.to().id() + " Fail to lock data object " + dobj.id() + " put " + request.toString() + " queue");
				System.out.println("     because it failed ");
			}
		}*/
	}

	@Override
	public void messageReceived(ExperimentRecorder recorder, Message message,
			double currentTime) {
		// TODO Auto-generated method stub
		//recorder.debug(this, "msgRcvd: " + message, currentTime);
		if (message.messageType() != MessageType.RequestLock) {
			recorder.warn(
					"RequestLockMessageHandler recieved " + 
					message.messageType() + " message."
					);
			return;
		}
		
		Node receiver = message.to();
		if(receiver.id() == request.getLeader().id()){
			Version tm = new Version(receiver.sequence(), message.from().id());
			request.setTM(tm);
			if(receiver.canLock(dobj.id(), request)){
				receiver.addGrantedRequest(dobj.id(), request);
				request.setGranted(true);
				Message m = super.createRequestLockResponseMessage(receiver, message.from(), request, true, message.purpose(), processor);
				//recorder.debug(this, "new msg: " + m, currentTime);
				experiment.messageQueue().enqueueMessage(m, currentTime);
			}
			else{
				receiver.addQueuedRequest(dobj.id(), request);
				request.setGranted(false);
			}
			
			LinkedList<Node> followers = processor.getFollowers();
			for(Node n : followers){
				Message m2 = super.createRequestLockResponseMessage(receiver, n, request, request.isGranted(), message.purpose(), processor);
				//recorder.debug(this, "new msg: " + m, currentTime);
				experiment.messageQueue().enqueueMessage(m2, currentTime);				
			}
		}
		else{
			boolean r = receiver.receiveClientRequest(request);
			if(r && request.isGranted()){
				Message m = super.createRequestLockResponseMessage(receiver, message.from(), request, true, message.purpose(), processor);
				//recorder.debug(this, "new msg: " + m, currentTime);
				experiment.messageQueue().enqueueMessage(m, currentTime);
				
			}
		}
	}
}
